package com.wl.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect //表示不是普通主键，这是一个切面类
public class MyAspect {

    @Before("myPointcut()") //before有个默认注解
    //直接用方法参数注入对象 => 这种方式叫接口注入
    public void before(JoinPoint jp) {
        long begin = System.currentTimeMillis();
        System.out.println("方法签名：jp.getSignature() = " + jp.getSignature());
        System.out.println("参数数组jp.getArgs() = " + Arrays.toString(jp.getArgs()));
        System.out.println("============前置拦截=============");
    }

    //目的在于定义表达式
    @Pointcut("execution(* com.wl..*UserMapper.*(..))")
    //切点方法  不需要些方法点内容，参数也不需要定义
    public void myPointcut() {}

    @After("myPointcut()")
    public void after(JoinPoint jp) {
        System.out.println("============后置拦截=============");
    }

    @AfterReturning(value = "myPointcut()", returning = "ret")
    public void afterReturning(Object ret) {
        //可以获取业务的返回值
        System.out.println("业务的返回值ret = " + ret);
        System.out.println("-------返回拦截------");
    }

    @AfterThrowing(value = "myPointcut()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Throwable e) {
        System.out.println("业务方法的异常 ret =" + e);
        System.out.println("-------异常拦截---------");
    }

    //环绕增强
    @Around("myPointcut()")
    public Object around(ProceedingJoinPoint jp) {
        //环绕增强业务方法是手动执行
        try {
            System.out.println("----------环绕增强：前置-----------");
            long begin = System.currentTimeMillis();
            Object ret = jp.proceed();
            long end = System.currentTimeMillis();
            System.out.println("共耗时：" + (end - begin) + "毫秒");
            System.out.println("----------环绕增强：返回-----------");
            //环绕增强的方法返回值就是业务方法的返回值
            return ret;
        } catch (Throwable e) {
            System.out.println("----------环绕增强：异常-----------");
            throw  new RuntimeException("业务方法出现异常", e);
        } finally {
            System.out.println("----------环绕增强：后置-----------");
        }
    }
}

    /*
     *
     * try{
     *   前置增强
     *   ---------> 业务方法
     *   返回增强
     * }catch(Exception e){
     *   异常增强
     * }finally{
     *   后置增强
     * }
     *
     * */

